package cw.itsource.service;

import cw.itsource.doc.EmployeeDoc;
import cw.itsource.util.HighlightResultMapper;
import cw.itsource.util.PageList;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.FuzzyQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.query.RangeQueryBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.sort.FieldSortBuilder;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;
import org.springframework.data.elasticsearch.core.aggregation.AggregatedPage;
import org.springframework.data.elasticsearch.core.query.NativeSearchQuery;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
public class EmployeeServiceImpl {

    @Autowired
    private ElasticsearchTemplate elasticsearchTemplate;
    @Autowired
    private HighlightResultMapper highlightResultMapper;

    public PageList<EmployeeDoc> searchHighlightByParam(String keyword){
        //查询条件：根据 name进行词条查询 且 年龄进行区间查询
        //1. 创建一个高级查询的条件构造器
        NativeSearchQueryBuilder searchQueryBuilder = new NativeSearchQueryBuilder();

        //2. 创建一个组合 查询条件
        BoolQueryBuilder boolQueryBuilder = new BoolQueryBuilder();

        //3. 分别创建出每一个子查询
        //3.1 根据name词条查询：
//        TermQueryBuilder termQueryBuilder = QueryBuilders.termQuery("userName", "蜜雪冰城");
//        //模糊查询匹配符 *
//        WildcardQueryBuilder termQueryBuilder = QueryBuilders.wildcardQuery("userName", "*蜜雪冰城*");
        //相似度查询：首先与词条进行相似度的匹配，匹配原则是：相似度超过50%，认为有效数据
        FuzzyQueryBuilder termQueryBuilder = QueryBuilders.fuzzyQuery("intro", keyword);
        //3.2 添加 年龄的区间查询
        RangeQueryBuilder rangeQueryBuilder = QueryBuilders.rangeQuery("age").gte(22).lte(30);
        //4. 将2个查询条件组合到一起，用 且连接
        boolQueryBuilder.must(termQueryBuilder).must(rangeQueryBuilder);

        //5. 将最终组合后的条件，保存到条件构造器中
        searchQueryBuilder.withQuery(boolQueryBuilder);

        //6. 添加一个分页查询的条件。
        //TODO 页码从0开始计数
        searchQueryBuilder.withPageable(PageRequest.of(0, 13));

        // 条件排序处理
        searchQueryBuilder.withSort(new FieldSortBuilder("age").order(SortOrder.ASC));

        //TODO 针对查询的结果 ，设置匹配关键字的高亮效果
        HighlightBuilder.Field field = new HighlightBuilder.Field("intro")
                .preTags("<font style='color:red;font-weight:bold'>").postTags("</font>");
        // 将设置的这个字段，添加到  条件构造器中
        searchQueryBuilder.withHighlightFields(field);

        //7. 根据条件构造器得到最终的查询条件对象
        NativeSearchQuery nativeSearchQuery = searchQueryBuilder.build();
//        //8. 调用repository内置的查询方法
//        Page<EmployeeDoc> page = employeeRepository.search(nativeSearchQuery);
        //TODO 2. 添加高亮字段后，还需要查询方式，使用 elasticsearchTemplate的模板API
        // SearchResultMapper : 这个提供了对 查询的结果进行自定义改造的API
        AggregatedPage<EmployeeDoc> aggregatedPage = elasticsearchTemplate.queryForPage(nativeSearchQuery, EmployeeDoc.class, highlightResultMapper);

        //9. 将查询的结果可以遍历出来
        //9.1 获取总记录数
        long totalElements = aggregatedPage.getTotalElements();
        //9.2 获取每一页的数据
        List<EmployeeDoc> content = aggregatedPage.getContent();

        return new PageList<>(totalElements, content);
    }
}
